from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from queue import Queue
from es import Es
from widgetUsb import UsbPort, UsbRead
from widgetMessage import msgDialog
import sys,os, json


# 左侧控件生成
class ElasticSearch(QWidget):
   def __init__(self, usb:UsbPort, config):
      super().__init__()
      self.config = config
      self.es = Es(self.config.get("server"), self.config.get("port"))
      
      self.threadsUsbRead = []
      self.usb = usb
      self.usbQueue = Queue()
      self.timer = QTimer()
      self.timer.timeout.connect(self.logFresh)
      self.timer.start(100)

      # 所有控件的创建
      self.buttonStartCollect = QPushButton("启动")
      self.buttonLocalUpload = QPushButton("离线上传")
      self.buttonUploadLog = QPushButton("实时上传")
      self.buttonStopCollect = QPushButton("结束收集")
      self.comboVender = QComboBox()
      for i in self.config.get("venders"):
         self.comboVender.addItem(i[0], i[1])
      self.comboVender.setCurrentIndex(0)
      self.comboProduct = QComboBox()
      for i in self.config.get("products"):
         self.comboProduct.addItem(i[0], i[1])
      self.comboProduct.setCurrentIndex(0)
      self.lineName = QLineEdit()
      self.lineName.setPlaceholderText("文件名")
      self.linePerson = QLineEdit()
      self.linePerson.setPlaceholderText("上传者姓名")
      self.lineDescription = QLineEdit()
      self.lineDescription.setPlaceholderText("日志描述, 例如场景,问题,参数等, 填写时请尽量详细")
      self.lineLocalLog = QLineEdit()
      self.lineLocalLog.setPlaceholderText("选择离线日志文件")
      self.buttonSelectFile = QPushButton("选择文件")
      self.log = QPlainTextEdit("")
      self.log.setPlaceholderText("设备日志")

      # 设置为只读
      self.log.setReadOnly(True)
      self.lineLocalLog.setReadOnly(True)
      
      self.layout()

   # 主程序
   def layout(self):
      

      # 左侧控件的尺寸
      self.leftWidgets = [ self.buttonStartCollect, 
                           self.comboVender, 
                           self.comboProduct, 
                           self.lineName, 
                           self.linePerson, 
                           self.lineDescription,
                           self.buttonUploadLog,
                           #self.buttonLogSave,
                           self.buttonStopCollect,
                           self.lineLocalLog,
                           self.buttonSelectFile,
                           self.buttonLocalUpload]

      #添加到列表中
      for w in self.leftWidgets:
         # w.setMaximumWidth(200)
         w.setMinimumHeight(30)


      # 左侧控件生成
      layoutControl = QGridLayout()

      layoutControl.addWidget(self.comboVender, 0,0)
      layoutControl.addWidget(self.comboProduct, 1,0)
      layoutControl.addWidget(self.lineName, 0,1)
      layoutControl.addWidget(self.linePerson,0,2)
      layoutControl.addWidget(self.lineDescription, 1,1,1,2)
      layoutControl.addWidget(self.buttonStartCollect,0,3)
      layoutControl.addWidget(self.lineLocalLog,1,3)
      layoutControl.addWidget(self.buttonStopCollect,0,4)
      layoutControl.addWidget(self.buttonSelectFile,1,4)
      layoutControl.addWidget(self.buttonUploadLog,0,5)
      layoutControl.addWidget(self.buttonLocalUpload,1,5)
      

      # 总布局，左侧是控制, 右侧是日志
      layout = QVBoxLayout()
      layout.addWidget(self.log)
      layout.addLayout(layoutControl)

      # 信号与槽
      self.buttonStartCollect.clicked.connect(self.startCollect)
      self.buttonStopCollect.clicked.connect(self.stopCollect)
      self.buttonLocalUpload.clicked.connect(self.logLocalUpload)
      self.buttonUploadLog.clicked.connect(self.logUpload)
      self.buttonSelectFile.clicked.connect(self.logSelect)

      self.setLayout(layout)
      self.setGeometry(100,100,1280,768)
      self.setWindowTitle("日志收集上传")
      

   # 清空日志
   def clearLog(self):
      self.log.clear()

   # 日志实时上传
   def logUpload(self):
      if self.logInfoCheck() is False:
         return
      response = self.logUploadRequest(self.log.toPlainText())

      if response.get("errno") is None or response.get("errno") != 0:
         msgDialog("错误", "上传失败, 请先保存到本地")
         self.logSave()
         return  
      msgDialog("提示", "上传成功")

   # 日志离线上传
   def logLocalUpload(self):
      if self.lineLocalLog.text() == '':
         msgDialog("错误", "请先选择文件")
         return

      try:
         open(self.lineLocalLog.text(), "rb")
      except:
         msgDialog("错误", "文件无法打开, 请重新选择")
         return
      
      if self.logInfoCheck() is False:
         return

      response = self.logUploadRequest(self.lineLocalLog.text())
      if response.get("errno") is None or response.get("errno") != 0:
         msgDialog("错误", "上传失败, 请先保存到本地")
         self.logSave()
         return  
      msgDialog("提示", "上传成功")

   # 日志文件选择
   def logSelect(self, path=""):
      dialog = QFileDialog()
      if dialog.exec():
         self.lineLocalLog.setText(dialog.selectedFiles()[0])
   

   # 日志刷新
   def logFresh(self):
      try:
         log = self.usbQueue.get(block=False)
         self.log.insertPlainText(log)
         self.log.moveCursor(QTextCursor.End)      # 让日志始终保持最后一行
      except: 
         pass
         
   # 启动日志采集
   def startCollect(self):
      if self.usb.device() is None:
         msgDialog("错误", "USB未找到,请先点击左侧usb识别")
         return
      
      # 将进程填充到列表中并启动
      if self.threadsUsbRead == []:
         for i in self.config.get("eps"):
            self.threadsUsbRead.append(UsbRead(self.usb, i))
         self.threadsUsbRead[0].setQueue(self.usbQueue)
         for i in self.threadsUsbRead:
            i.start()
         msgDialog("提示", "usb识别成功, 开启%d个读取进程" % len(self.threadsUsbRead))
      else:
         countAlive = self.countThreadAlive()
         total = len(self.threadsUsbRead)
         if self.countThreadAlive() != 0:
            msgDialog("提示", "当前读取进程正在运行 %d/%d" % (countAlive, total))
         else:
            msgDialog("提示", "当前进程因错误退出 %d/%d, 请再次点击识别usb" % (countAlive, total))
            self.stopCollect()

   # 结束收集
   def stopCollect(self):
      msgDialog("提示", "退出所有进程 %d/%d" % (len(self.threadsUsbRead), len(self.threadsUsbRead)))
      self.log.clear()
      for i in self.threadsUsbRead:
         i.exit()
      self.threadsUsbRead = []

   # 日志上传函数
   def logUploadRequest(self, content):
      response = self.es.esUpload(self.comboVender.currentData(),
                                 self.comboProduct.currentData(),
                                 self.lineName.text(),
                                 self.linePerson.text(),
                                 self.lineDescription.text(),
                                 content)
      return response
   # 日志信息检查
   def logInfoCheck(self):
      if self.lineName.text().__len__() < 5:
         msgDialog("错误", "文件名太短")
         return False
      if self.lineDescription.text().__len__() < 10:
         msgDialog("错误", "描述过于简单")
         return False
      if self.linePerson.text().__len__()  < 2:
         msgDialog("错误", "请认真填写上传者姓名")
         return False

      return True

   def countThreadAlive(self):
      countAlive = 0
      for i in self.threadsUsbRead:
         if i.is_alive():
            countAlive += 1
      return countAlive


